{- This file is part of funbot.
 -
 - Written in 2015, 2016 by fr33domlover <fr33domlover@riseup.net>.
 -
 - ♡ Copying is an act of love. Please copy, reuse and share.
 -
 - The author(s) have dedicated all copyright and related and neighboring
 - rights to this software to the public domain worldwide. This software is
 - distributed without any warranty.
 -
 - You should have received a copy of the CC0 Public Domain Dedication along
 - with this software. If not, see
 - <http://creativecommons.org/publicdomain/zero/1.0/>.
 -}

{-# LANGUAGE OverloadedStrings #-}

module FunBot.Commands.Puppet
    ( cmdPuppetStart
    , cmdPuppetEnd
    --, cmdPuppetStatus
    , cmdPuppetSay
    , cmdPuppetEcho
    )
where

import Formatting ((%))
import FunBot.Puppet
import FunBot.Types
import FunBot.Util
import Network.IRC.Fun.Bot.Chat
import Network.IRC.Fun.Bot.Types
import Network.IRC.Fun.Color.Format (formatMsg)
import Network.IRC.Fun.Color.Format.Long
import Network.IRC.Fun.Types.Base

import qualified Data.Text as T

start :: Channel -> Nickname -> (MsgContent -> BotSession ()) -> BotSession ()
start chan nick send = do
    result <- puppetStart chan nick
    send $ case result of
        Just False ->
            formatMsg
                (nickname % ", I already have " % channel % " in puppet mode.")
                nick chan
        Just True ->
            formatMsg
                ( nickname
                % ", you aren’t listed as a puppeteer for "
                % channel
                )
                nick chan
        Nothing   ->
            formatMsg
                (nickname % ", puppet mode started for " % channel)
                nick chan

respondPuppetStart :: Respond
respondPuppetStart Nothing _nick [] send =
    send "Please specify a channel, or use this command in a channel."
respondPuppetStart (Just chan) nick [] send = start chan nick send
respondPuppetStart _mchan nick [chant] send =
    let chan = Channel chant
    in  if looksLikeChan chan
            then start chan nick send
            else send $ notchan chan
respondPuppetStart mchan nick args _send =
    failBack mchan nick $ WrongNumArgsN (Just $ length args) Nothing

cmdPuppetStart :: BotCmd
cmdPuppetStart = Command
    { cmdNames    = cmds ["puppet-start"]
    , cmdRespond  = respondPuppetStart
    , cmdHelp     = helps
        [ ( "puppet-start"
          , "enable puppet mode in the current channel"
          )
        , ( "puppet-start <channel>"
          , "enable puppet mode in the given channel"
          )
        ]
    , cmdExamples =
        [ "puppet-start"
        , "puppet-start #freepost-bot"
        ]
    }

end :: Channel -> Nickname -> (MsgContent -> BotSession ()) -> BotSession ()
end chan nick send = do
    result <- puppetEnd chan nick
    send $ case result of
        Just False ->
            formatMsg
                (nickname % ", I don’t have " % channel % " in puppet mode.")
                nick chan
        Just True ->
            formatMsg
                ( nickname
                % ", you aren’t listed as a puppeteer for "
                % channel
                )
                nick chan
        Nothing   ->
            formatMsg
                (nickname % ", puppet mode ended for " % channel)
                nick chan

respondPuppetEnd :: Respond
respondPuppetEnd Nothing _nick [] send =
    send "Please specify a channel, or use this command in a channel."
respondPuppetEnd (Just chan) nick [] send = end chan nick send
respondPuppetEnd _mchan nick [chant] send =
    let chan = Channel chant
    in  if looksLikeChan chan
            then end chan nick send
            else send $ notchan chan
respondPuppetEnd mchan nick args _send =
    failBack mchan nick $ WrongNumArgsN (Just $ length args) Nothing

cmdPuppetEnd :: BotCmd
cmdPuppetEnd = Command
    { cmdNames    = cmds ["puppet-end"]
    , cmdRespond  = respondPuppetEnd
    , cmdHelp     = helps
        [ ( "puppet-end"
          , "stop puppet mode in the current channel"
          )
        , ( "puppet-end <channel>"
          , "stop puppet mode in the given channel"
          )
        ]
    , cmdExamples =
        [ "puppet-end"
        , "puppet-end #freepost-bot"
        ]
    }

respondPuppetSay :: Bool -> Respond
respondPuppetSay reveal _mchan nick (chant : ws@(_:_)) send =
    let chan = Channel chant
    in  if looksLikeChan chan
            then do
                let msg = MsgContent $ T.unwords ws
                result <- puppetSay chan nick msg reveal
                send $ case result of
                    Just False ->
                        formatMsg
                            ( nickname
                            % ", I don’t have "
                            % channel
                            % " in puppet mode."
                            )
                            nick chan
                    Just True ->
                        formatMsg
                            ( nickname
                            % ", you didn’t start puppet mode for "
                            % channel
                            )
                            nick chan
                    Nothing ->
                        formatMsg
                            (nickname % ", I sent the message to " % channel)
                            nick chan
            else send $ notchan chan
respondPuppetSay _reveal mchan nick args _send =
    failBack mchan nick $ WrongNumArgsN (Just $ length args) (Just 2)

cmdPuppetSay :: BotCmd
cmdPuppetSay = Command
    { cmdNames    = cmds ["puppet-say"]
    , cmdRespond  = respondPuppetSay True
    , cmdHelp     = helps
        [ ( "puppet-say <channel> <message>"
          , "while in puppet mode, ask me to say something in the channel. I \
            \will reveal the message comes from you. If you don’t want that, \
            \see the puppet-echo command."
          )
        ]
    , cmdExamples =
        [ "puppet-say #freepost Hello world!"
        ]
    }

cmdPuppetEcho :: BotCmd
cmdPuppetEcho = Command
    { cmdNames    = cmds ["puppet-echo"]
    , cmdRespond  = respondPuppetSay False
    , cmdHelp     = helps
        [ ( "puppet-echo <channel> <message>"
          , "while in puppet mode, ask me to say something in the channel. I \
            \won’t reveal the message comes from you. Also see the puppet-say \
            \command."
          )
        ]
    , cmdExamples =
        [ "puppet-echo #freepost Hello world!"
        ]
    }
